mod authentication;
mod authorization;
mod cache;
mod menus;
mod role;
mod user;
mod organ;

pub use authentication::*;
pub use authorization::*;
pub use menus::*;

use shq_common::prelude::{ Deptment, MenuItem, Permission, Role, TreeNode};


pub fn get_menus() -> anyhow::Result<Vec<MenuItem>> {
    // 获取菜单配置
    let menus=get_menus_conf();
    // 根据父id获取菜单列表
    let menus = menus.get_menus_by_pid(None);
    // 定义一个空菜单列表
    let mut top_menus:Vec<MenuItem>=Vec::new();
    // 如果菜单列表不为空
    if let Some(menus) = menus {
        // 遍历菜单列表
        for m in menus {
            // 创建菜单项
            let menu=MenuItem::new(m.id, m.name.clone(), m.component.clone(), m.permission.clone(), m.children.clone());
            // 将菜单项添加到菜单列表中
            top_menus.push(menu);
        }
    }
    // 返回菜单列表
    Ok(top_menus)
}
pub async fn get_menus_user_id(user_id: u32) -> anyhow::Result<Vec<MenuItem>> {
    let menus = get_menus_conf();
    let menus = menus.get_menus_by_pid_user_id(None,user_id).await;
    Ok(menus)
}
pub async fn get_menus_by_pid(pid: u32, user_id: u32) -> Vec<MenuItem> {
    let menus = get_menus_conf();
    let menus = menus.get_menus_by_pid_user_id(Some(pid),user_id).await;
    menus
}
pub async fn get_roles() -> anyhow::Result<Vec<Role>> {
    use role::get_roles_list;
    let roles = get_roles_list().await?;
    Ok(roles)
}
pub async fn get_deptment_list() -> anyhow::Result<Vec<Deptment>> {
    use organ::get_deptment_list;
    let roles = get_deptment_list().await?;
    Ok(roles)
}
pub async fn get_user() -> anyhow::Result<Vec<TreeNode>> {
    use user::get_user_menu;
    let roles = get_user_menu().await?;
    Ok(roles)
}
pub async fn user_menu_component(user_id: u32) -> anyhow::Result<Vec<(u32, Permission)>> {
    let roles = get_perms_by_user_id(user_id).await?;
    Ok(roles)
}
pub async fn get_role_users_by_organ(role_id: u32, organ_id: u32) -> anyhow::Result<Vec<u32>> {
    let uids=get_role_user_ids(role_id).await?;
    let mut ec = shq_common::prelude::empl::EmployeeCache::new()?;
    let mut res:Vec<u32>=Vec::new();
    for uid in uids.iter() {
        if let Ok(did) = ec.get_dept_id_by_user_id(*uid).await {
            if did == organ_id {
                res.push(*uid) ;
            }
        } else {
            continue;
        }
    }
    Ok(res)
}
#[cfg(test)]
mod tests {
    use crate::menus::init_menus_conf;

    use super::*;
    use shq_common::prelude::{AuthType, ColumnRange, Permission, RowRange};
    use tracing_subscriber::{filter::LevelFilter, prelude::*};
    #[tokio::test]
    async fn test_login() {
        dotenv::dotenv().ok();
        let stdout_log = tracing_subscriber::fmt::layer().pretty();
        tracing_subscriber::registry()
            .with(LevelFilter::INFO)
            .with(stdout_log)
            .init();
        shq_common::prelude::init_app_config().await.unwrap();
        init_menus_conf().unwrap();
        let res = user_login("999999","shjxkh").await;
        match res {
            Ok(u) => {
                assert_eq!(u.name, "分行公共");
            }
            Err(err) => panic!("user_login error:{err}"),
        }
    }
    #[tokio::test]
    async fn test1() {
        dotenv::dotenv().ok();
        let stdout_log = tracing_subscriber::fmt::layer().pretty();
        tracing_subscriber::registry()
            .with(LevelFilter::INFO)
            .with(stdout_log)
            .init();
        shq_common::prelude::init_app_config().await.unwrap();
        init_menus_conf().unwrap();
        let res = get_menus_user_id(2046).await;
        match res {
            Ok(plist) => {
                println!("get_menus:0:{:?}", plist);
                assert_eq!(plist.len(), 3);
            }
            Err(err) => panic!("get_user_permission error:{err}"),
        }
    }
    #[tokio::test]
    async fn test2() {
        dotenv::dotenv().ok();
        let stdout_log = tracing_subscriber::fmt::layer().pretty();
        tracing_subscriber::registry()
            .with(LevelFilter::INFO)
            .with(stdout_log)
            .init();
        shq_common::prelude::init_app_config().await.unwrap();
        init_menus_conf().unwrap();
        let plist = get_menus_by_pid(200,2046).await;
        println!("get_menus_by_pid:100:{:?}", plist);
        assert_eq!(plist.len(), 1);
    }
    #[tokio::test]
    async fn test3() {
        dotenv::dotenv().ok();
        let stdout_log = tracing_subscriber::fmt::layer().pretty();
        tracing_subscriber::registry()
            .with(LevelFilter::INFO)
            .with(stdout_log)
            .init();
        shq_common::prelude::init_app_config().await.unwrap();
        init_menus_conf().unwrap();
        let p1 = (
            2208,
            Permission {
                auth_types: vec![AuthType::Select, AuthType::Import],
                row_ranges: vec![],
                column_ranges: vec![],
            },
        );
        let p2 = (
            8033,
            Permission {
                auth_types: vec![AuthType::Select],
                row_ranges: vec![RowRange::OneSelf, RowRange::DeptSelf],
                column_ranges: vec![],
            },
        );
        let p3 = (
            8034,
            Permission {
                auth_types: vec![AuthType::Select],
                row_ranges: vec![RowRange::All],
                column_ranges: vec![ColumnRange::Comp, ColumnRange::Pay, ColumnRange::CompSmall],
            },
        );
        let res = perms_to_role(6, vec![p1.clone(), p2.clone(), p3.clone()]).await;
        if let Err(err) = res {
            panic!("perms_to_role error:{err}");
        }
        let res = perms_to_user(10, vec![p1, p2, p3]).await;
        if let Err(err) = res {
            panic!("perms_to_role error:{err}");
        }
        let res = users_to_role(6, vec![6, 9]).await;
        if let Err(err) = res {
            panic!("users_to_role error:{err}");
        }
        let has = has_auth_type(6, 8034, AuthType::Edit).await.unwrap();
        assert_eq!(has, false);
        let has = has_auth_type(9, 8034, AuthType::Edit).await.unwrap();
        assert_eq!(has, false);
        let has = has_auth_type(9, 2208, AuthType::Import).await.unwrap();
        assert_eq!(has, true);
        let has = has_row_range(9, 2208, RowRange::All).await.unwrap();
        assert_eq!(has, true);
        let has = has_row_range(9, 8033, RowRange::DeptSelf).await.unwrap();
        assert_eq!(has, true);
        let has = has_auth_type(10, 8034, AuthType::Edit).await.unwrap();
        assert_eq!(has, false);
        let has = has_auth_type(10, 8034, AuthType::Edit).await.unwrap();
        assert_eq!(has, false);
        let has = has_auth_type(10, 2208, AuthType::Import).await.unwrap();
        assert_eq!(has, true);
        let has = has_row_range(10, 2208, RowRange::All).await.unwrap();
        assert_eq!(has, true);
        let has = has_row_range(10, 8033, RowRange::DeptSelf).await.unwrap();
        assert_eq!(has, true);
        let p = get_user_perm(9, 8034).await.unwrap();
        if let Some(p) = p {
            assert_eq!(p.auth_types.len(), 2);
        } else {
            panic!("get_user_perm error");
        }
    }
    
    #[tokio::test]
    async fn test4() {
        dotenv::dotenv().ok();
        let stdout_log = tracing_subscriber::fmt::layer().pretty();
        tracing_subscriber::registry()
            .with(LevelFilter::INFO)
            .with(stdout_log)
            .init();
        shq_common::prelude::init_app_config().await.unwrap();
        init_menus_conf().unwrap();
        let plist = get_menus_by_pid(200,2046).await;
        println!("get_menus_by_pid:100:{:?}", plist);
        assert_eq!(plist.len(), 1);
    }
}
